---
title: Redis
date: 2023-06-20 22:10:43
images: https://kodo.huixiangwuyou.com/blog/images/redis.png
summary: Redis（Remote Dictionary Server）是一个开源的、基于内存的键值存储系统，通常被用作数据库、缓存和消息中间件。它以其高性能、灵活的数据结构和丰富的功能而闻名，广泛应用于缓存、会话存储、实时分析、消息队列等场景。
tags: 
 - SQLDB
---




## 核心特点
- 基于内存：数据存储在内存中，读写速度极快，适合高性能场景。
- 键值存储：数据以键值对的形式存储，键是字符串，值可以是多种数据结构。
- 持久化：支持数据持久化到磁盘，防止数据丢失。
- 丰富的数据结构：支持字符串、列表、集合、哈希、有序集合等多种数据结构。
- 高可用性：支持主从复制和哨兵模式，提供故障转移功能。
- 分布式：通过 Redis Cluster 实现数据分片和分布式存储。
- 原子操作：支持事务和 Lua 脚本，确保操作的原子性。
- 发布/订阅：支持消息的发布和订阅，适合消息队列场景。


### 持久化机制   

Redis 提供两种持久化方式：
- RDB（Redis Database Backup）
    - 定期将内存中的数据快照保存到磁盘。
    - 优点：文件紧凑，恢复速度快。
    - 缺点：可能丢失最后一次快照后的数据。
- AOF（Append-Only File）：
    - 记录所有写操作日志，通过重放日志恢复数据。
    - 优点：数据丢失少，可读性强。
    - 缺点：文件较大，恢复速度较慢。

<br/>

### 高可用性与扩展性

- 主从复制
    - 主节点（Master）负责写操作，从节点（Slave）负责读操作和数据冗余。
    - 从节点通过复制主节点的数据实现数据同步。
- 哨兵模式（Sentinel）：
    - 监控主从节点的状态，自动进行故障转移。
- Redis Cluster：
    - 分布式集群模式，支持数据分片和自动故障转移。

<br/>

### 应用场景

- 缓存：将常用数据存储在内存中，减少数据库访问，提高响应速度。
- 会话存储：存储用户会话信息，如登录状态、购物车等。
- 消息队列：实现异步消息处理，解耦系统组件。
- 排行榜：使用有序集合存储排行榜数据，支持实时更新。
- 实时分析：利用有序集合和位图进行实时统计和分析。
- 分布式锁：使用 Redis 的 SETNX 命令实现分布式锁。
- 排行榜：利用有序集合实现实时排行榜。


<br/>

###  优缺点

- 优点：
  - 高性能，读写速度极快。
  - 支持多种数据结构，功能丰富。
  - 支持持久化和高可用性。
  - 社区活跃，生态系统丰富。
- 缺点：
  - 数据存储在内存中，成本较高。
  - 不适合存储大规模数据。
  - 持久化机制可能导致数据丢失。

### 核心概念
通过键值对的形式存储数据，每个键对应一个值。
- 键（Key）：键是一个字符串，用于唯一标识数据。
- 值（Value）：值可以是多种数据结构，如字符串、列表、集合、哈希、有序集合等。
- 数据结构：Redis 支持多种数据结构，如字符串、列表、集合、哈希、有序集合等。

<br/> 


## 实践

### 基本操作
```bash
# 进入redis-cli数据库
redis-cli -h 127.0.0.1 -p 6379

# 修改配置
nano /etc/redis/redis.conf

# 字符串，用于存储简单的键值对。
SET key value
GET key
# 有序的字符串列表，支持从两端插入和删除。
LPUSH list value
LRANGE list 0 -1
SADD set value
# 无序的字符串集合，支持去重和集合运算。
SADD myset "item1"
SADD myset "item2"
SMEMBERS myset

# 哈希表，用于存储键值对。
HSET user:1 name "Alice"
HGET user:1 name

# 有序集合，用于存储有序的键值对。
ZADD myzset 1 "item1"
ZADD myzset 2 "item2"
ZRANGE myzset 0 -1 WITHSCORES

#删除数据
DEL key

#清空数据 阻塞
FLUSHDB  # 当前数据
FLUSHALL #所有数据
#清空数据 非阻塞
FLUSHDB ASYNC
FLUSHALL ASYNC

# 发布/订阅，用于消息的发布和订阅。
PUBLISH channel message
SUBSCRIBE channel

# 事务，用于保证多个操作的原子性。
MULTI
SET key value
GET key
EXEC

# Lua 脚本，用于执行复杂的操作。
EVAL "return redis.call('GET', KEYS[1])" 1 key
```

### 过期设置

> 使用 SET 命令
```shell
SET token_key token_value EX seconds [NX|XX]
EX seconds：设置过期时间（秒）。
NX：仅当 key 不存在时设置（用于避免覆盖已有 Token）。
XX：仅当 key 已存在时设置。

# 设置 Token（有效期 3600 秒） user:token 使用有意义的前缀便于管理和清理
127.0.0.1:6379> SET user:token:123 "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9" EX 3600 NX
OK

# 查看 Token
127.0.0.1:6379> GET user:token:123
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9"

# 查看剩余过期时间（秒）
127.0.0.1:6379> TTL user:token:123
(integer) 3598
```

> 分步操作（SET + EXPIRE）
```shell
SET token_key token_value
EXPIRE token_key seconds

# 设置 Token
127.0.0.1:6379> SET user:token:456 "another_token"
OK

# 设置过期时间（3600 秒）
127.0.0.1:6379> EXPIRE user:token:456 3600
(integer) 1
```

> 使用 SETEX 命令
```shell
# 重新设置过期时间为 3600 秒
127.0.0.1:6379> EXPIRE user:token:123 3600
(integer) 1

# 使用 PEXPIRE 设置毫秒级过期时间
127.0.0.1:6379> PEXPIRE user:token:123 3600000  # 3600 秒 = 3600000 毫秒
(integer) 1
```

> 查看|移除过期时间
```shell
# 查看剩余过期时间（秒）
127.0.0.1:6379> TTL user:token:123
(integer) 1800  # 剩余 1800 秒

# 查看剩余过期时间（毫秒）
127.0.0.1:6379> PTTL user:token:123
(integer) 1800000  # 剩余 1800000 毫秒

127.0.0.1:6379> PERSIST user:token:123
(integer) 1  # 成功移除过期时间
```


### 远程连接

redis是默认不支持远程连接的，需要修改配置文件
远程工具下载：https://goanother.com/cn/

```bash
# 开启 6379 端口
firewall-cmd --zone=public --add-port=6379/tcp --permanent
firewall-cmd --reload

uwf allow 6379
# 修改配置文件
nano /etc/redis/redis.conf

# 注释掉 bind 127.0.0.1  或者该为 bind 0.0.0.0
# bind 127.0.0.1

# 设置保护模式为 no
protected-mode no

# 设置密码
requirepass 123456  

# 重启redis
systemctl restart redis

# ！注意 ！注意 ！注意  若是远程连接不成功，可以关闭redis然后重启
systemctl stop redis
systemctl status redis
systemctl start redis
```


![连接示例](https://kodo.huixiangwuyou.com/blog/images/db/20250625232053.png)


<br/>  

### 总结  

Redis 是一个高性能、灵活且功能丰富的内存数据库，适合需要快速数据访问和复杂数据操作的场景。它的多种数据结构、持久化机制和高可用性使其成为缓存、会话存储、实时分析和消息队列等场景的理想选择。无论是小型项目还是大规模分布式系统，Redis 都能提供出色的支持。